/*
    Copyright 2011 Peter Pratscher
 
    This file is part of Surveillance.NET.

    Surveillance.NET is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    Surveillance.NET is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Surveillance.NET. If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using System.Threading;
using SurveillanceDotNet.Model;

namespace SurveillanceDotNet
{
    public partial class SurveillanceCameraForm : Form
    {
        private const string NO_VIDEO_DEVICE = "No video device found!";

        public List<string> CamerasInUse { get; set; }
        FilterInfoCollection videoDevices;

        public SurveillanceCamera Camera { get; set; }

        private bool _EditMode = false;

        public SurveillanceCameraForm()
        {
            InitializeComponent();
        }

        private void SurveillanceCameraForm_Load(object sender, EventArgs e)
        {
            tbSensitivity.Visible = false;
            cbxLocalCameras.Visible = false;
            pbxVideo.Visible = false;
            vpbCurrentMotion.Visible = false;
            lblAlarm.Visible = false;
            btnClearAlarm.Visible = false;
            btnSave.Enabled = false;
            lblCameraPicture.Visible = false;
            lblLocalCameras.Visible = false;
            lblMotionLevel.Visible = false;
            lblSensitivity.Visible = false;
            btnAdjustSettings.Visible = false;

            cbxCameraType.SelectedIndex = 0;

            if (this.Camera != null)
            {
                _EditMode = true;

                cbxCameraType.Enabled = false;

                cbxLocalCameras.Items.Clear();
                cbxLocalCameras.Items.Add(this.Camera.Name);
                cbxLocalCameras.SelectedIndex = 0;
                cbxLocalCameras.Enabled = false;

                tbSensitivity.Value = this.Camera.ScaleFactor;
            }
        }

        private void cbxCameraType_SelectedIndexChanged(object sender, EventArgs e)
        {
            //Only used for new cameras
            if (cbxCameraType.SelectedIndex == 0)
            {
                cbxLocalCameras.Visible = true;
                lblLocalCameras.Visible = true;

                videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);

                if (videoDevices.Count == 0)
                {
                    cbxLocalCameras.Items.Add(NO_VIDEO_DEVICE);
                    return;
                }

                foreach (FilterInfo filterInfo in videoDevices)
                {
                    cbxLocalCameras.Items.Add(filterInfo.Name);
                }

                if (this.CamerasInUse != null && this.CamerasInUse.Count > 0)
                {
                    foreach (string s in this.CamerasInUse)
                    {
                        if (cbxLocalCameras.Items.Contains(s))
                        {
                            cbxLocalCameras.Items.Remove(s);
                        }
                    }
                }
            }
        }

        private void cbxLocalCameras_SelectedIndexChanged(object sender, EventArgs e)
        {
            StopCamera();

            if (cbxLocalCameras.SelectedItem.ToString() == NO_VIDEO_DEVICE) return;

            if (!_EditMode)
            {
                string moniker = "";

                foreach (FilterInfo filterInfo in videoDevices)
                {
                    if (filterInfo.Name == cbxLocalCameras.SelectedItem.ToString())
                    {
                        moniker = filterInfo.MonikerString;
                        break;
                    }
                }

                if (moniker == "") return;

                this.Camera = new SurveillanceCamera(moniker);
            }

            tbSensitivity.Visible = true;
            pbxVideo.Visible = true;
            vpbCurrentMotion.Visible = true;
            lblAlarm.Visible = false;
            btnClearAlarm.Visible = false;
            btnSave.Enabled = true;
            lblCameraPicture.Visible = true;
            lblMotionLevel.Visible = true;
            lblSensitivity.Visible = true;
            btnAdjustSettings.Visible = true;
            
            this.Camera.NewSurveillancePicture += new NewSurveillancePictureHandler(Camera_NewSurveillancePicture);
            this.Camera.Alarm += new AlarmEventHandler(Camera_Alarm);
            this.Camera.StartMonitoring();
        }

        void Camera_Alarm(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate
                {
                    lblAlarm.Visible = true;
                    btnClearAlarm.Visible = true;
                }));
            }
            else
            {
                lblAlarm.Visible = true;
                btnClearAlarm.Visible = true;
            }
            
        }

        void Camera_NewSurveillancePicture(object sender, EventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(delegate
                {
                    vpbCurrentMotion.Value = this.Camera.MotionLevel;
                    pbxVideo.Image = this.Camera.CurrentFrame;
                }));
            }
            else
            {
                vpbCurrentMotion.Value = this.Camera.MotionLevel;
                pbxVideo.Image = this.Camera.CurrentFrame;
            }
            
        }

        private void StopCamera()
        {
            if (this.Camera == null) return;
            this.Camera.NewSurveillancePicture -= Camera_NewSurveillancePicture;
            this.Camera.Alarm -=Camera_Alarm;
            this.Camera.StopMonitoring();
        }

        private void SurveillanceCameraForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            StopCamera();
        }

        private void btnAdjustSettings_Click(object sender, EventArgs e)
        {
            VideoCaptureDevice device = (VideoCaptureDevice)this.Camera.Source.VideoSource;
            device.DisplayPropertyPage(this.Handle);
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            this.Camera.Name = cbxLocalCameras.SelectedItem.ToString();
            this.DialogResult = DialogResult.OK;
        }

        private void tbSensitivity_Scroll(object sender, EventArgs e)
        {
            this.Camera.ScaleFactor = tbSensitivity.Value;
        }

        private void btnClearAlarm_Click(object sender, EventArgs e)
        {
            lblAlarm.Visible = false;
            btnClearAlarm.Visible = false;
        }
    }
}
